package com.nlp.visualization.service.tasks;

import com.google.gson.Gson;
import com.nlp.visualization.common.CONSTANTS;
import com.nlp.visualization.core.seg.ISegmentService;
import com.nlp.visualization.core.seg.SegmentFactory;
import com.nlp.visualization.core.seg.SegmentType;
import com.nlp.visualization.core.seg.filter.SegFilter;
import com.nlp.visualization.pojo.NLP.weibo.WeiboCSVEntity;
import com.nlp.visualization.pojo.NLP.weibo.WeiboContentEntity;
import com.nlp.visualization.pojo.NLP.weibo.WeiboSegEntity;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RecursiveAction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.nlp.visualization.common.CONSTANTS.TASK_MAX;

public class WeiboSegTask extends RecursiveAction {


    Logger logger = LoggerFactory.getLogger(WeiboSegTask.class);
    // 每个"小任务"最多只50个数
    private static final int MAX = TASK_MAX;

    private int start;
    private int end;
    private List<WeiboCSVEntity> lines;
    //    private StringBuffer segBuff;
    private ConcurrentLinkedQueue<WeiboSegEntity> queue;
    private SegmentType method;
    private SegFilter filter;

    public WeiboSegTask(int start, int end, List lines, ConcurrentLinkedQueue<WeiboSegEntity> queue, SegmentType method, SegFilter filter) {
        this.start = start;
        this.end = end;
        this.lines = lines;
        this.queue = queue;
        this.method = method;
        this.filter = filter;

    }

    @Override
    protected void compute() {
        // 当end-start的值小于MAX时候，开始执行任务
        if ((end - start) < MAX) {
            for (int i = start; i < end; i++) {
                Gson gson = new Gson();
                //将文件读到的json转换成初始文件的实体
                WeiboCSVEntity csv = lines.get(i);
                //将微博的内容转成微博info的对象
                WeiboContentEntity weiboContent = gson.fromJson(csv.getWeibo_info().replaceAll("\\\\", ""), WeiboContentEntity.class);
                //实例化一个要返回的对象
                WeiboSegEntity seg = new WeiboSegEntity();
                //判断是否是原创微博
                if (!weiboContent.isIs_reprint_weibo()) {
                    //分词过程，往seg里面添加信息
                    fillSeg(csv, weiboContent, seg, method, filter);
//                    segBuff.append(new Gson().toJson(seg) + ",\n");
                    queue.add(seg);
                } else {
                    //不是原创微博，跳过本条记录
                    continue;
                }
            }
        } else {
            // 将大任务分解成两个小任务
            int middle = (start + end) / 2;
            WeiboSegTask left = new WeiboSegTask(start, middle, lines, queue, method, filter);
            WeiboSegTask right = new WeiboSegTask(middle, end, lines, queue, method, filter);
            // 并行执行两个小任务
            left.fork();
            right.fork();
        }
    }


    /**
     * 填充返回的数据
     *
     * @param csv          一条csv数据的实体
     * @param weiboContent 一条微博内容的实体
     * @param seg          一条分词后的返回类型的实体
     * @param method       采用分词的方式
     */
    private void fillSeg(WeiboCSVEntity csv, WeiboContentEntity weiboContent, WeiboSegEntity seg, SegmentType method, SegFilter filter) {

        ISegmentService segmentService = SegmentFactory.getInstance();
        try {

            //头部
            seg.setStatus(CONSTANTS.STATUS);
            seg.setVersion(CONSTANTS.VERSION);
            seg.setWeibo_publish_time(getTimeFromStr(weiboContent.getPublish_time()));
            seg.setWeibo_user_id(csv.getUser_id());
            seg.setWeibo_id(csv.getWeibo_id());

            //分词
            WeiboSegEntity.ResultsBean result = new WeiboSegEntity.ResultsBean();
            //设置初始文本
            result.setText(weiboContent.getWeibo_content().split("\u200B\u200B\u200B")[0]);
            String content = weiboContent.getWeibo_content().split("\u200B\u200B\u200B")[0];
            content = filterEmoji(content);
            List<String> segResults = segmentService.executeSeg(content, method, filter);
            Iterator iterator = segResults.iterator();
            int count = 0;
            while (iterator.hasNext()) {
                String term = (String) iterator.next();
                if (term.trim().equals(""))
                    continue;
                String[] terms = term.split("/");
                String word = "";
                String pos = "";
                word = terms[0];
                if (terms.length > 1)
                    pos = terms[1];
                WeiboSegEntity.ResultsBean.ItemsBean itemsBean = new WeiboSegEntity.ResultsBean.ItemsBean();
                //设置id
                itemsBean.setId(count);
                count++;
                //设置字节长度
                itemsBean.setByte_length(term.toString().getBytes().length);
                //设置词汇的标准化表达，主要针对时间、数字单位，没有归一化表达的，此项为空串
                itemsBean.setFormal("");
                //设置词汇的字符串
                itemsBean.setItem(word);
                //设置pos词性
                itemsBean.setPart_of_speech(pos);
                //最细粒度的分词
                List<String> baselist = new ArrayList<>();
                List<String> minTerms = segmentService.executeSeg(word, SegmentType.ANSJ_BASIC, filter);
                for (String s : minTerms) {
                    baselist.add(s.toString().split("/")[0]);
                }
                itemsBean.setBasic_words(baselist);

                //设置该词发布的时间
                itemsBean.setWords_publish_time(getTimeFromStr(weiboContent.getPublish_time()));
                //设置该词的发布作者
                itemsBean.setWords_belong_user_id(csv.getUser_id());
                //设置该词所属的微博id
                itemsBean.setWords_belong_weibo_id(csv.getWeibo_id());
                //添加进数组中
                result.getItems().add(itemsBean);

            }

            //把result添加进seg里面
            seg.setResults(result);
        } catch (Exception e) {
            logger.error("分词异常");
            e.printStackTrace();
        }

    }

    /**
     * 提取微博中的时间
     *
     * @param str
     * @return
     */
    private String getTimeFromStr(String str) {
        str = str.replace("今天", "2017-10-19");
        Pattern pattern = Pattern.compile("[0-9]{4}[-][0-9]{1,2}[-][0-9]{1,2}[ ][0-9]{1,2}[:][0-9]{1,2}[:][0-9]{1,2}");
        Matcher matcher = pattern.matcher(str);
        String dateStr = "";
        if (matcher.find()) {
            dateStr = matcher.group(0);
        }
        if (dateStr.equals("")) {
            pattern = Pattern.compile("[0-9]{1,2}月[0-9]{1,2}日[ ][0-9]{1,2}[:][0-9]{1,2}");
            matcher = pattern.matcher(str);
            if (matcher.find()) {
                dateStr = matcher.group(0);
                dateStr = dateStr.replace("月", "-");
                dateStr = dateStr.replace("日", "");
                dateStr = "2017-" + dateStr + ":00";
            }

        }
        if (dateStr.equals(""))
            return "2017-10-19 00:00:00";
        return dateStr.toString();
    }


    /**
     * 判断该微博词汇是否有效
     *
     * @param term
     * @return
     */
    private boolean IsVaildTerm(String term) {
        boolean flag = false;
        String[] terms = term.split("/");
        //是不是有效字符
        flag = terms.length > 1;
        if (flag) {
            if (terms[1].equals("w"))
                flag = false;
        }
        return flag;

    }

    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    /**
     * 过滤emoji 或者 其他非文字类型的字符
     *
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return source;
        }
        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            return source;
        } else {
            if (buf.length() == len) {
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
    }
}
